#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <cstdlib>
#include <functional>
#include <vector>
#include <sys/wait.h>

// void handler(int sig)
// {
//     std::cout << "获得了一个信号：" << sig << std::endl;

// }

// int main()
// {
//     signal(SIGINT, handler);

//     int cnt = 0;
//     while (1)
//     {
//         std::cout << "hello test " <<cnt++<< std::endl;
//         sleep(1);
//     }

//     return 0;
// }

// void handler(int sig)
// {
//     std::cout << "获得了一个信号：" << sig << std::endl;
// }

// int main()
// {
//     // 捕捉所有信号
//     for (int i = 1; i <= 31; i++)
//     {
//         signal(i, handler);
//     }

//     for (int i = 1; i <= 31; i++)
//     {
//         if(i == 9)
//         {
//             continue;
//         }
//         std::cout << "尝试发送" << i << "信号" << std::endl;
//         kill(getpid(), i);
//         sleep(1);
//     }

//     int cnt = 0;
//     while (1)
//     {
//         std::cout << "hello test " << cnt++ << " pid: " << getpid() << std::endl;
//         sleep(1);
//     }

//     return 0;
// }

// void handler(int sig)
// {
//     std::cout << "获得了一个信号：" << sig << std::endl;
// }

// int main()
// {
//     // 捕捉所有信号
//     for (int i = 1; i <= 31; i++)
//     {
//         signal(i, handler);
//     }

//     //尝试发送abort
//     abort();

//     int cnt = 0;
//     while (1)
//     {
//         std::cout << "hello test " << cnt++ << " pid: " << getpid() << std::endl;
//         sleep(1);
//     }

//     return 0;
// }

// void handler(int sig)
// {
//     std::cout << "获得了一个信号：" << sig << std::endl;
//     exit(1);
// }

// int main()
// {

//     // 捕捉所有信号
//     for (int i = 1; i <= 31; i++)
//     {
//         signal(i, handler);
//     }

//     // // 尝试修改字符串常量，查看收到的信号
//     // char *msg = "Hello World";
//     // *msg = 'W';

//     // 尝试除0
//     int a = 10;
//     a /= 0;

//     int cnt = 0;
//     while (1)
//     {
//         std::cout << "hello test " << cnt++ << " pid: " << getpid() << std::endl;
//         sleep(1);
//     }
//     return 0;
// }

// void handler(int sig)
// {
//     std::cout << "获得了一个信号：" << sig << std::endl;
//     exit(1);
// }

// int main()
// {

//     // 捕捉所有信号
//     for (int i = 1; i <= 31; i++)
//     {
//         signal(i, handler);
//     }

//     //设置一个闹钟alarm
//     alarm(5);

//     int cnt = 0;
//     while (1)
//     {
//         std::cout << "hello test " << cnt++ << " pid: " << getpid() << std::endl;
//         sleep(1);
//     }
//     return 0;
// }

// int main()
// {

//     //设置一个闹钟alarm
//     alarm(1);

//     int cnt = 0;
//     while (1)
//     {
//         std::cout << "hello test " << cnt++ << " pid: " << getpid() << std::endl;
//         sleep(1);
//     }
//     return 0;
// }

// int cnt = 0;
// void handler(int sig)
// {
//     std::cout<<"收到了一个信号："<<sig<<" cnt = "<<cnt<<std::endl;
//     exit(1);
// }

// int main()
// {

//     //捕捉SIGALRM信号
//     signal(SIGALRM,handler);

//     //设置一个闹钟alarm
//     alarm(1);

//     while (1)
//     {
//         cnt++;
//     }
//     return 0;
// }

// void handler(int sig)
// {
//     std::cout << "获得了一个信号：" << sig <<std::endl;
//     alarm(1);//反复设置闹钟
// }

// int main()
// {

//     signal(SIGALRM,handler);

//     //设置一个闹钟alarm
//     alarm(1);

//     int cnt = 0;
//     while (1)
//     {
//         std::cout << "hello test " << cnt++ << " pid: " << getpid() << std::endl;
//         sleep(1);
//     }
//     return 0;
// }

// // //////////func////////////
// void Sched()
// {
//     std::cout << "我是进程调度" << std::endl;
// }
// void MemManger()
// {
//     std::cout << "我是周期性的内存管理，正在检查有没有内存问题" << std::endl;
// }
// void Fflush()
// {
//     std::cout << "我是刷新程序，我在定期刷新内存数据，到磁盘" << std::endl;
// }
// // /////////////////////////

// using func_t = std::function<void()>;
// std::vector<func_t> funcs;

// void handler(int sig)
// {
//     for(int i = 0;i < funcs.size();i++)
//     {
//         funcs[i]();
//     }
//     alarm(1);//反复设置闹钟
// }

// int main()
// {

//     funcs.push_back(Sched);
//     funcs.push_back(MemManger);
//     funcs.push_back(Fflush);

//     signal(SIGALRM,handler);

//     //设置一个闹钟alarm
//     alarm(1);

//     int cnt = 0;
//     while (1)
//     {
//         pause();
//     }
//     return 0;
// }

// //1.自定义捕捉信号
// void handler(int sig)
// {
//     std::cout << "获得了一个信号：" << sig << std::endl;

// }

// int main()
// {
//     signal(SIGINT, handler);

//     int cnt = 0;
//     while (true)
//     {
//         std::cout << "hello test " <<cnt++<< std::endl;
//         sleep(1);
//     }

//     return 0;
// }

// //2.忽略信号

// int main()
// {
//     signal(SIGINT, SIG_IGN);

//     int cnt = 0;
//     while (true)
//     {
//         std::cout << "hello test " <<cnt++<< std::endl;
//         sleep(1);
//     }

//     return 0;
// }

// //3.默认处理信号
// int main()
// {
//     signal(SIGINT, SIG_DFL);

//     int cnt = 0;
//     while (true)
//     {
//         std::cout << "hello test " <<cnt++<< std::endl;
//         sleep(1);
//     }

//     return 0;
// }

// // 打印pending表
// void PrintPending(sigset_t *pending)
// {
//     // 由高位向低位打印
//     for (int i = 31; i > 0; i--)
//     {
//         std::cout << sigismember(pending, i);
//     }
//     std::cout << std::endl;
// }

// // 我们尝试阻塞（屏蔽）2号信号，也就意味着，当收到2号信号，pending会由0至1，并且不会被递达。
// // 我们获取pending并打印。
// // 看到pending由全0，变成由1个比特位变成1。
// int main()
// {
//     // 阻塞2号信号
//     sigset_t block;
//     sigset_t o_block;
//     // 置空block表-初始化
//     sigemptyset(&block);
//     sigemptyset(&o_block);
//     // 设置block表-屏蔽2号信号
//     sigaddset(&block, 2);
//     // 设置进入进程
//     sigprocmask(SIG_SETMASK, &block, &o_block);

//     while (true)
//     {
//         sigset_t pending;
//         sigemptyset(&pending);
//         // 获取pending
//         sigpending(&pending);
//         PrintPending(&pending);
//         sleep(1);
//     }

//     return 0;
// }

// // 打印pending表
// void PrintPending(sigset_t *pending)
// {
//     // 由高位向低位打印
//     for (int i = 31; i > 0; i--)
//     {
//         std::cout << sigismember(pending, i);
//     }
//     std::cout << std::endl;
// }

// // 捕捉2号信号
// void handler(int sig)
// {
//     std::cout << "/////////////////////" << std::endl;
//     std::cout << "递达" << sig << "号信号!" << std::endl;
//     sigset_t pending;
//     sigemptyset(&pending);
//     PrintPending(&pending);
//     std::cout << "/////////////////////" << std::endl;
//     exit(1);
// }

// // 我们尝试阻塞（屏蔽）2号信号，也就意味着，当收到2号信号，pending会由0至1，并且不会被递达。
// // 我们获取pending并打印。
// // 看到pending由全0，变成由1个比特位变成1。
// int main()
// {
//     signal(2, handler);

//     // 阻塞2号信号
//     sigset_t block;
//     sigset_t o_block;
//     // 置空block表-初始化
//     sigemptyset(&block);
//     sigemptyset(&o_block);
//     // 设置block表-尝试屏蔽(阻塞)所有信号
//     for (int i = 1; i <= 31; i++)
//     {
//         sigaddset(&block, i);
//     }
//     // 设置进入进程
//     sigprocmask(SIG_SETMASK, &block, &o_block);

//     int cnt = 0;
//     while (true)
//     {
//         sigset_t pending;
//         sigemptyset(&pending);
//         // 获取pending
//         sigpending(&pending);
//         // 打印
//         PrintPending(&pending);

//         cnt++;
//         if (cnt == 10)
//         {
//             // 解除对2号信号的屏蔽
//             sigprocmask(SIG_SETMASK, &o_block, nullptr);
//         }
//         sleep(1);
//     }

//     return 0;
// }


// //测试volatile关键字
// volatile int flag = 0;//不要优化flag，保证内存可见性
// void handler(int signum)
// {
//     std::cout<<"修改flag变量"<<std::endl;
//     flag = 1;
// }

// int main()
// {

//     signal(SIGINT,handler);

//     while(!flag)
//     {
//         ;
//     }

//     std::cout<<"program exit normal"<<std::endl;

//     return 0;
// }


// //验证子进程发送SIGCHID信号

// void handler(int signum)
// {
//     std::cout<<"hello sig: "<<signum<<std::endl;
// }
// int main()
// {
//     //父进程捕捉信号
//     signal(SIGCHLD,handler);

//     int n = fork();
//     if(n == 0)
//     {
//         //子进程-三秒后退出
//         sleep(3);
//         exit(1);
//     }

//     //父进程死循环
//     while(true)
//     {
//         ;
//     }

//     return 0;
// }


//设计新的进程等待方案

// void WaitAll(int signum)
// {
//     //version1-尝试阻塞等待
//     while(true)
//     {
//         int n = waitpid(-1,nullptr,0);
//         if(n > 0)
//         {
//             std::cout<<"等待成功！"<<std::endl;
//         }
//         else if(n < 0)
//         {
//             std::cout<<"等待失败！"<<std::endl;
//             break;
//         }
//     }
//     //std::cout<<"hello sig: "<<signum<<std::endl;
// }

// int main()
// {

//     //父进程捕捉SIGSHLD信号
//     signal(SIGCHLD,WaitAll);

//     //创建10个子进程，5秒后退出
//     for(int i = 0;i < 10;i++)
//     {
//         int n = fork();
//         if(n == 0)
//         {
//             //子进程
//             sleep(5);
//             exit(1);
//         }
//     }
    
//     //父进程
//     while(true)
//     {
//         ;
//     }
//     return 0;
// }

// void WaitAll(int signum)
// {
//        //version2-尝试非阻塞等待待
//     while(true)
//     {
//         int n = waitpid(-1,nullptr,WNOHANG);
//         //等到了会接着等，只要等不到就不等了
//         if(n == 0)
//         {
//             //没有等到
//             break;
//         }
//         else if(n < 0)
//         {
//             std::cout<<"等待失败！"<<std::endl;
//             break;
//         }
//     }
//     //std::cout<<"hello sig: "<<signum<<std::endl;
// }

// int main()
// {

//     //父进程捕捉SIGSHLD信号
//     signal(SIGCHLD,WaitAll);

//     //创建10个子进程，5秒后退出
//     for(int i = 0;i < 10;i++)
//     {
//         int n = fork();
//         if(n == 0)
//         {
//             //子进程 一部分退出一部分不退
//             sleep(5);
//             if(i >= 5)
//             {
//                 sleep(10);
//             }
//             exit(1);
//         }
//     }
    
//     //父进程
//     while(true)
//     {
//         std::cout<<"I am father"<<std::endl;
//         sleep(1);
//     }
//     return 0;
// }


//version3-调用signal/sigaction自动回收
int main()
{
    struct sigaction act,oact;
    act.sa_handler = SIG_IGN;
    //父进程捕捉SIGSHLD信号
    //signal(SIGCHLD,SIG_IGN);
    sigaction(SIGCHLD,&act,&oact);
    //创建10个子进程，5秒后退出
    for(int i = 0;i < 10;i++)
    {
        int n = fork();
        if(n == 0)
        {
            //子进程 一部分退出一部分不退
            sleep(5);
            if(i >= 5)
            {
                sleep(10);
            }
            exit(1);
        }
    }
    
    //父进程
    while(true)
    {
        std::cout<<"I am father"<<std::endl;
        sleep(1);
    }
    return 0;
}